import os
from functools import lru_cache
from os import path

from dotenv import load_dotenv
from pydantic import BaseModel

# __all__ = ['get_settings']
# 获取当前文件的绝对路径
current_file = os.path.abspath(__file__)

# 获取当前文件所在的目录
current_dir = os.path.dirname(current_file)

# 假设项目根目录是当前文件的父目录的父目录
ENV_FILES = ('.env.dev', '.env.prod')
ROOT_PATH = os.path.dirname(os.path.dirname(current_dir))


class BaseSettings(BaseModel):
    """配置基类
        server目录为后端项目根目录, 在该目录下创建 ".env" 文件, 写入环境变量(默认大写)会自动加载, 并覆盖同名配置(小写)
            eg.
            .env 文件内写入:
                UPLOAD_DIRECTORY='/tmp/test/'
                REDIS_URL='redis://localhost:6379'
                DATABASE_URL='mysql+pymysql://root:root@localhost:3306/happy?charset=utf8mb4'

                上述环境变量会覆盖 upload_directory 和 redis_url

        说明：当配置文件存在同名配置时，优先使用配置文件配置，否则使用默认配置
            每个应用里面都有配置文件，会继承 该配置，
            当配置文件里面配置项覆盖了父配置，则子配置会覆盖父配置，否则父配置会覆盖子配置
            如果配置文件不存在，则使用默认配置
            根目录下面的 .env 里面是敏感数据，不会上传，需要现场配置
            根据不用的环境会调用不同的配置文件.env.producton .env.development
            一般 子应用配置的是个性化 差异化特性。保证不重复配置，也能适合不同的应用场景
    """

    model_config = {
        "ignored_types": (int, set, str),
        "arbitrary_types_allowed": True,
    }

    # 上传文件路径
    upload_directory: str = '/tmp/uploads/happy-python/'
    # 上传图片限制
    upload_image_size = 1024 * 1024 * 10
    # 上传视频限制
    upload_video_size = 1024 * 1024 * 30
    # 上传图片扩展
    upload_image_ext = {'png', 'jpg', 'jpeg', 'gif', 'ico', 'bmp'}
    # 上传视频扩展
    upload_video_ext = {'mp4', 'mp3', 'avi', 'flv', 'rmvb', 'mov'}
    # 上传路径URL前缀
    upload_prefix = '/api/uploads'

    # 数据源配置
    # database_url: str = 'mysql+pymysql://root:root@localhost:3306/happy?charset=utf8mb4'
    # mysql
    MYSQL_USERNAME = os.getenv("MYSQL_USERNAME") or "root"
    MYSQL_PASSWORD = os.getenv("MYSQL_PASSWORD") or "qq741456"
    MYSQL_DOMAIN = os.getenv("MYSQL_DOMAIN") or "localhost"
    MYSQL_PORT = os.getenv("MYSQL_PORT") or 3306
    MYSQL_DATABASE = os.getenv("MYSQL_DATABASE") or "test"
    # database_url: str = f"mysql+pymysql://{MYSQL_USERNAME}:{MYSQL_PASSWORD}@{MYSQL_DOMAIN}:{MYSQL_PORT}/{MYSQL_DATABASE}"
    database_url: str = 'mysql+pymysql://root:qq741456@localhost:3306/coupon?charset=utf8mb4'
    # 数据库连接池最小值
    database_pool_min_size: int = 5
    # 数据库连接池最大值
    database_pool_max_size: int = 20
    # 数据库连接最大空闲时间
    database_pool_recycle: int = 300

    # Redis源配置
    redis_url: str = 'redis://localhost:6379'

    # 是否启用静态资源
    enabled_static: bool = True
    # 静态资源URL路径
    static_path: str = '/api/static'
    # 静态资源本地路径
    static_directory: str = path.join(ROOT_PATH, 'static')

    # CORS 跨域资源共享
    # 允许跨域的源列表 eg. '["*"]'   '["http://localhost", "http://localhost:8080", "https://www.example.org"]'
    cors_allow_origins: str = '["*"]'

    # 模式
    mode: str = 'prod'  # dev, prod

    # 全局配置
    # 版本
    version: str = 'v1.1.0'
    # 项目根路径
    root_path: str = ROOT_PATH
    # 默认请求超时
    request_timeout: int = 15
    # Mysql表前缀
    table_prefix: str = 'la_'
    # 时区
    timezone: str = 'Asia/Shanghai'
    # 日期时间格式
    datetime_fmt: str = '%Y-%m-%d %H:%M:%S'
    # 系统加密字符
    secret: str = 'UVTIyzCy'
    # Redis键前缀
    redis_prefix: str = 'Like:'
    # 短信验证码
    redis_sms_code: str = 'smsCode:'
    # 禁止修改操作 (演示功能,限制POST请求)
    disallow_modify: bool = False
    # 当前域名
    domain = 'http://127.0.0.1:8000'
    # 短信验证码
    redisSmsCode = "smsCode:"

    # JWT配置
    """
    配置 OAuth2 密码流认证方式
    官方文档：https://fastapi.tiangolo.com/zh/tutorial/security/first-steps/#fastapi-oauth2passwordbearer
    auto_error:(bool) 可选参数，默认为 True。当验证失败时，如果设置为 True，FastAPI 将自动返回一个 401 未授权的响应，如果设置为 False，你需要自己处理身份验证失败的情况。
    这里的 auto_error 设置为 False 是因为存在 OpenAuth：开放认证，无认证也可以访问，
    如果设置为 True，那么 FastAPI 会自动报错，即无认证时 OpenAuth 会失效，所以不能使用 True。
    """
    # oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/api/login", auto_error=False) if OAUTH_ENABLE else lambda: ""
    """安全的随机密钥，该密钥将用于对 JWT 令牌进行签名"""
    SECRET_KEY = 'vgb0tnl9d58+6n-6h-ea&u^1#s0ccp!794=kbvqacjq75vzps$'
    """用于设定 JWT 令牌签名算法"""
    ALGORITHM = "HS256"
    """access_token 过期时间，一天"""
    ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 60 * 24 * 1
    """refresh_token 过期时间，用于刷新token使用，两天"""
    REFRESH_TOKEN_EXPIRE_MINUTES = 60 * 60 * 24 * 7
    """access_token 缓存时间，用于刷新token使用，30分钟"""
    ACCESS_TOKEN_CACHE_MINUTES = 30
    '''token白名单'''
    WHITE_LIST: list[str] = [
        "/admin/user/login",
        "/admin/user/login_out",
        "/docs",
        "/apijson.json",
        # "/admin/user/list"
    ]
    '''
    微信配置
    '''
    wechat_appid = ""
    wechat_secret = ""


@lru_cache()
def get_settings() -> BaseSettings:
    """获取并缓存应用配置"""
    # 读取server目录下的配置
    for f in ENV_FILES:
        load_dotenv(dotenv_path=path.join(ROOT_PATH, f))
        print("读取配置文件:", ROOT_PATH)
        print("dotenv_path", path.join(ROOT_PATH, f))
        print("mysql---url", BaseSettings().database_url)
    return BaseSettings()


# p = path.dirname(path.abspath(path.join(__file__, '..')))
# print(os.getcwd())
# print("root_path", ROOT_PATH)


if __name__ == "__main__":
    # p = path.dirname(path.abspath(path.join(__file__, '..')))
    # print("root_path", p)
    wechat_appid = get_settings().wechat_appid
    print("wechat_appid", wechat_appid)
